#!/bin/bash

echo "#The whole HSTA flow"
echo "#Author: Min Li, Contact: mli46@wisc.edu"
echo -ne "#Generated Date: "
date
echo 

## The following three variables are global viewable
export HSTA_ROOT=~/hybrid-sta/
export HSTA_BENCHMARK_DIR=$HSTA_ROOT/Bench/$1/
export HSTA_TIMING_DIR=$HSTA_ROOT/Timing/
export HSTA_PG_DIR=$HSTA_ROOT/PG/
export HSTA_POWER_PROFILING_DIR=$HSTA_ROOT/Power_Profiling/
export HSTA_THERMAL_DIR=$HSTA_ROOT/Thermal/

## Default lib
export HSTA_TECH_LIB=$HSTA_ROOT/TSMC_LIB_2013/NLDM/tcbn45gsbwp_120a/tcbn45gsbwpwc.lib
#export HSTA_TECH_DB=$HSTA_ROOT/TSMC_LIB_2013/NLDM/tcbn45gsbwp_120a/tcbn45gsbwpwc.db
export HSTA_BENCHMARK=$1
export HSTA_INIT_RUN=$2
export HSTA_MODE_ID=$3
set_id=$4
is_pred=$5
export HSTA_SET_CNT=30


## ------------------------------- Step 1 ----------------------------------
## ------- Get the placed bechmark file and group gates into regions -------
## --- Defining the Power Grid based on the technology that we are using ---

## If it is the first time, generate the PG bench and region file
if [ "$HSTA_MODE_ID" == "-1" ]
then
    export HSTA_PP_REPORT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".pp_report"
    export HSTA_PTRACE_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".ptrace"$set_id"_"$is_pred
    export HSTA_STEADY_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".std"
    export HSTA_TCL_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".tcl"
    export HSTA_RPT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".rpt_"$set_id"_"$is_pred
    export HSTA_RPT_REPORT=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".rpt_rp_"$set_id"_"$is_pred
    export HSTA_PG_SOL_FILE=$HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK".sol_"$set_id"_"$is_pred
else
    export HSTA_PP_REPORT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".pp_report_"$HSTA_MODE_ID
    export HSTA_PTRACE_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".ptrace_"$HSTA_MODE_ID"_"$set_id"_"$is_pred
    export HSTA_STEADY_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".std_"$HSTA_MODE_ID
    export HSTA_TCL_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".tcl_"$HSTA_MODE_ID
    export HSTA_RPT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".rpt_"$HSTA_MODE_ID"_"$set_id"_"$is_pred
    export HSTA_RPT_REPORT=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".rpt_rp_"$HSTA_MODE_ID"_"$set_id"_"$is_pred
    export HSTA_PG_SOL_FILE=$HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK".sol_"$HSTA_MODE_ID"_"$set_id"_"$is_pred
fi

export HSTA_FLP_FILE=$HSTA_BENCHMARK_DIR$HSTA_BENCHMARK".flp"
export HSTA_INIT_FILE=$HSTA_BENCHMARK_DIR$HSTA_BENCHMARK".hotspot_init"
export HSTA_PTRACE_FILE_TEMP=$HSTA_PTRACE_FILE"_tmp" # generated in hotspot_pp_interface.sh
export HSTA_REGION_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".reg"
export HSTA_TCL_TEMPLATE_FILE=$HSTA_TCL_FILE".tpl"

## ',' is the delimiter
OIFS="$IFS"
IFS=','
set -- $(awk '{
if (lines > 0){
   --lines;
}
if (lines == 1){
   print;
   exit;
}
} 
/"TSMC64K_Lowk_Conservative"/{
     lines = 8
}' < $HSTA_TECH_LIB |  awk -vRS=")" -vFS="(" '{print $2}' )
IFS="$OIFS"

export res_per_unit_len=$2
echo "Resistence per unit length is: "$res_per_unit_len

export VDD=$(awk '
/nom_voltage : /{
     print $3;
     exit;
}' < $HSTA_TECH_LIB |  awk -vRS=":" -vFS=";" '{print $1}')
echo "VDD is: "$VDD


HSTA_PG_BENCHMARK=$HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK".spice"
if [ "$HSTA_INIT_RUN" == "0" ]
then
    if [ ${HSTA_BENCHMARK:0:1} == "S" ]
    then
        HSTA_GRID_CNT=4
        # S38584: 38ns
        HSTA_CYCLE_PERIOD=4
    elif [ ${HSTA_BENCHMARK:0:3} == "b17" ]
    then
        HSTA_GRID_CNT=6
        HSTA_CYCLE_PERIOD=6
    elif [ ${HSTA_BENCHMARK:0:3} == "DMA" ]
    then
        HSTA_GRID_CNT=6
        HSTA_CYCLE_PERIOD=8
    elif [ ${HSTA_BENCHMARK:0:3} == "b22" ]
    then
        HSTA_GRID_CNT=8
        HSTA_CYCLE_PERIOD=6
    elif [ ${HSTA_BENCHMARK:0:3} == "dsp" ]
    then
        HSTA_GRID_CNT=8
        HSTA_CYCLE_PERIOD=40
    elif [ ${HSTA_BENCHMARK:0:3} == "b18" ]
    then
        HSTA_GRID_CNT=10
        HSTA_CYCLE_PERIOD=10
    elif [ ${HSTA_BENCHMARK:0:3} == "des" ]
    then
        HSTA_GRID_CNT=12
        HSTA_CYCLE_PERIOD=6
    else
        echo "No such benchmark!"
    fi
    
    echo "Entering $HSTA_PG_DIR..."
    cd $HSTA_PG_DIR
    ## Generating .flp .reg .spice
    echo "Init run... Generating PG benchmark..."
    source ./PG_bench_gen.sh $HSTA_GRID_CNT

## Update the current source of the power grid benchmark based on the power profiling results
else
    
    if [ ${HSTA_BENCHMARK:0:1} == "S" ]
    then
        HSTA_REG_CNT=8
        HSTA_X_GRID_CNT=2
        HSTA_Y_GRID_CNT=2
    elif [ ${HSTA_BENCHMARK:0:3} == "b17" ]
    then
        HSTA_REG_CNT=12
        HSTA_X_GRID_CNT=2
        HSTA_Y_GRID_CNT=6
    elif [ ${HSTA_BENCHMARK:0:3} == "DMA" ]
    then
        HSTA_REG_CNT=12
        HSTA_X_GRID_CNT=2
        HSTA_Y_GRID_CNT=6
    elif [ ${HSTA_BENCHMARK:0:3} == "b22" ]
    then
        HSTA_REG_CNT=32
        HSTA_X_GRID_CNT=4
        HSTA_Y_GRID_CNT=8
    elif [ ${HSTA_BENCHMARK:0:3} == "dsp" ]
    then
        HSTA_REG_CNT=32
        HSTA_X_GRID_CNT=4
        HSTA_Y_GRID_CNT=8
    elif [ ${HSTA_BENCHMARK:0:3} == "b18" ]
    then
        HSTA_REG_CNT=60  
        HSTA_X_GRID_CNT=6
        HSTA_Y_GRID_CNT=10
    elif [ ${HSTA_BENCHMARK:0:3} == "des" ]
    then
        HSTA_REG_CNT=72
        HSTA_X_GRID_CNT=6
        HSTA_Y_GRID_CNT=12
    else
        echo "No such benchmark!"
    fi    
fi

export HSTA_REG_CNT
export HSTA_GRID_CNT
export HSTA_CYCLE_PERIOD
export HSTA_X_GRID_CNT
export HSTA_Y_GRID_CNT    

## ------------------------------- Step 2 ----------------------------------
## ------------------- Trace selection for each region ---------------------

## Generating a trace list (done beforehand)

## ------------------------------- Step 3 ----------------------------------
## ------------------ Generate switching activity info ---------------------
## predicted or real
if [ "$HSTA_MODE_ID" == "-1" ]
then
    export HSTA_CONTROL_INPUT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".assign"
    export HSTA_SW_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw"
    export HSTA_SW_FILE_GOLD=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_gold"
    export HSTA_SW_FILE_PRED=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_pred"
    export HSTA_SW_FILE_AVG=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_avg"
    export HSTA_SW_FILE_SRR=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_srr"
    export HSTA_SW_FILE_BC=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_bc"
    export HSTA_SW_FILE_WC=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_wc"
    export HSTA_PROB_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".bench.prob"
else
    export HSTA_CONTROL_INPUT_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".assign_"$HSTA_MODE_ID
    export HSTA_SW_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID
    export HSTA_SW_FILE_GOLD=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_gold"
    export HSTA_SW_FILE_PRED=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_pred"
    export HSTA_SW_FILE_AVG=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_avg"
    export HSTA_SW_FILE_SRR=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_srr"
    export HSTA_SW_FILE_BC=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_bc"
    export HSTA_SW_FILE_WC=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".sw_"$HSTA_MODE_ID"_wc"
    export HSTA_PROB_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".bench.prob_"$HSTA_MODE_ID
fi

export HSTA_UNIQ_TMP_FILE=$HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".temp_"$HSTA_MODE_ID"_"$set_id"_"$is_pred

## mv to the same file name will cause problem
## change "[]" into "__"
if [ "$HSTA_INIT_RUN" == "0" ]
then
    cd $HSTA_BENCHMARK_DIR
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_GOLD > $HSTA_UNIQ_TMP_FILE"_2" && mv $HSTA_UNIQ_TMP_FILE"_2" $HSTA_SW_FILE_GOLD
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_PRED > $HSTA_UNIQ_TMP_FILE && mv $HSTA_UNIQ_TMP_FILE $HSTA_SW_FILE_PRED
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_AVG > $HSTA_UNIQ_TMP_FILE"_1" && mv $HSTA_UNIQ_TMP_FILE"_1" $HSTA_SW_FILE_AVG
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_SRR > $HSTA_UNIQ_TMP_FILE"_3" && mv $HSTA_UNIQ_TMP_FILE"_3" $HSTA_SW_FILE_SRR
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_BC > $HSTA_UNIQ_TMP_FILE"_4" && mv $HSTA_UNIQ_TMP_FILE"_4" $HSTA_SW_FILE_BC
    ~/hybrid-sta/Bench/BenchCovs/removeSquareBrac.sh $HSTA_SW_FILE_WC > $HSTA_UNIQ_TMP_FILE"_5" && mv $HSTA_UNIQ_TMP_FILE"_5" $HSTA_SW_FILE_WC
fi

#exit

## PG Analysis for ini_sol file
echo "Entering $HSTA_PG_DIR..."
cd $HSTA_PG_DIR
echo "Generating PG analysis erquired files..."
echo "Report power grid benchmark generation time..."
/usr/bin/time ./PI $HSTA_PG_BENCHMARK
echo
echo "Performing power grid analysis and reporting runtime..."
/usr/bin/time ./umfpack_HSTA $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_info $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_row \
    $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_col $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_val $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.B > $HSTA_PG_SOL_FILE
echo

## ------------------------------- Step 4 ----------------------------------
## ------ Power profiling and generate Hotspot required input files --------

## Generating the .tcl for pt
echo "Entering $HSTA_POWER_PROFILING_DIR..."
cd $HSTA_POWER_PROFILING_DIR
## Input is the set id, for real case, set_id>=3
#for set_id in {7..9}
#do
#set_id=7
hotspot_cycle_cnt=0
if [ "$is_pred" -eq 3 ]
then
    echo "!!!Using predicted SW data!!!"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_PRED
elif [ "$is_pred" -eq 2 ]
then
    echo "---Using average SW data---"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_AVG
elif [ "$is_pred" -eq 1 ]
then
    echo "---Using gold SW data---"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_GOLD
elif [ "$is_pred" -eq 4 ]
then
    echo "---Using BC SW data---"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_BC
elif [ "$is_pred" -eq 5 ]
then
    echo "---Using WC SW data---"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_WC
else
    echo "---Using srr SW data---"
    export HSTA_CUR_SW_FILE=$HSTA_SW_FILE_SRR
fi

echo "!!!Current SW set id is "$set_id

## Note that .tcl is region related, whenever .reg changes, it should re-gen!!
if [ "$HSTA_INIT_RUN" == "0" ]
then
    echo "Reporting initial [power_profiling].tcl generation time..."
    /usr/bin/time ./HSTA_ptpx_gen.sh $set_id > $HSTA_TCL_FILE
else
    echo "Updating [power_profiling].tcl, swapping SW set..."
    /usr/bin/time ./HSTA_ptpx_update.sh $set_id
fi

if [ $? -ne 0 ]
then
    echo "Update tcl file failed!!!"
    exit
fi
echo

## Generating the .sdc and .spef file 
## Since time consuming (for spef), once and done
#if [ "$HSTA_INIT_RUN" == "0" ]
#then
    #cd $HSTA_TIMING_DIR
    #echo "Report sdc and spef generation time \(init and done\)..."
    #/usr/bin/time ./sdc_spef_gen.sh
    #echo
    #exit
#fi


##************************************************************************************
##~~~~~~~~~~~~~~Loop for convergence, power_report -> ib -> pg_analysis~~~~~~~~~~~~~~~
##************************************************************************************
#echo "Enter loop for convergence \(only when temperature is considered\)"
#itr_cnt=1
#while [ 1 ] 
#do
#echo "Iteration "$itr_cnt":"

cp $HSTA_PG_SOL_FILE $HSTA_PG_SOL_FILE"_init"

echo "Entering $HSTA_POWER_PROFILING_DIR..."
cd $HSTA_POWER_PROFILING_DIR

echo "Entering $HSTA_TIMING_DIR..."
## Power analysis HSTA_PTRACE_FILE_TEMP updated with pp analysis
echo "Report power profiling time..."
/usr/bin/time pt_shell -f $HSTA_TCL_FILE > $HSTA_PP_REPORT_FILE
if [ $? -ne 0 ]
then
    echo "Power profiling failed!!!"
    exit
fi
## update ptrace_tmp file
./ptrace_temp_file_gen.sh

if [ "$HSTA_INIT_RUN" == "0" ]
then
    if [ "$HSTA_MODE_ID" == "-1" ]
    then
        cp $HSTA_PTRACE_FILE_TEMP $HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".ptrace_tmp"
    else
        cp $HSTA_PTRACE_FILE_TEMP $HSTA_BENCHMARK_DIR\/$HSTA_BENCHMARK".ptrace_"$HSTA_MODE_ID"_tmp"
    fi
fi
echo

## For init_run, exit here!!!
#exit

cp $HSTA_PG_BENCHMARK $HSTA_PG_BENCHMARK.bck
echo "Updating PG \(.spice\) benchmark based on power profiling report..."
echo "Old file create date:"
ls -lt $HSTA_PG_BENCHMARK
cd $HSTA_ROOT
./update_iB.sh $HSTA_X_GRID_CNT $HSTA_Y_GRID_CNT $HSTA_PTRACE_FILE_TEMP > $HSTA_UNIQ_TMP_FILE
awk '/iB/ {$NF=""}1' $HSTA_PG_BENCHMARK | awk -v vdd=$VDD -v ptrace_tmp=$HSTA_UNIQ_TMP_FILE '{ \
   if(/iB/) {printf $0; getline < ptrace_tmp; printf("%.4f\n", $1/vdd)} \
   else {print}}' > $HSTA_UNIQ_TMP_FILE"_1"
mv $HSTA_UNIQ_TMP_FILE"_1" $HSTA_PG_BENCHMARK
echo "New file create date:"
ls -lt $HSTA_PG_BENCHMARK
echo 

## PG Analysis
echo "Entering $HSTA_PG_DIR..."
cd $HSTA_PG_DIR
echo "Generating PG analysis erquired files..."
echo "Report power grid benchmark generation time..."
time ./PI $HSTA_PG_BENCHMARK
echo "Report power grid analysis time..."
time ./umfpack_HSTA $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_info $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_row \
    $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_col $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.A_val $HSTA_BENCHMARK_DIR/$HSTA_BENCHMARK.B > $HSTA_PG_SOL_FILE
echo

echo "Listing out the difference of solutions of two consecutive iterations"
diff $HSTA_PG_SOL_FILE"_init" $HSTA_PG_SOL_FILE
echo

## Parse the PG solution
HSTA_PG_DIMENTION=$(awk '/Dimention is / {print $3; exit}' $HSTA_PG_SOL_FILE)
awk -v dim=$HSTA_PG_DIMENTION -v flag=0 '/x \(solution of Ax=b\): Printing results.../ {flag = 1} {if(flag==1) {getline; for(i=0;i<dim;i++) {getline; print $3} exit}}' $HSTA_PG_SOL_FILE"_init" \
| awk -F'(' '{print $2}' | awk -F')' '{print $1}' > $HSTA_UNIQ_TMP_FILE"_init.txt"

awk -v dim=$HSTA_PG_DIMENTION -v flag=0 '/x \(solution of Ax=b\): Printing results.../ {flag = 1} {if(flag==1) {getline; for(i=0;i<dim;i++) {getline; print $3} exit}}' $HSTA_PG_SOL_FILE \
| awk -F'(' '{print $2}' | awk -F')' '{print $1}' > $HSTA_UNIQ_TMP_FILE

paste $HSTA_UNIQ_TMP_FILE $HSTA_UNIQ_TMP_FILE"_init.txt" > $HSTA_UNIQ_TMP_FILE"_1.txt"
## The gap threshold here is 0.5
break_flag=$(awk 'function abs(x){return ((x < 0.0) ? -x : x)} BEGIN{sum=0} {sum += abs($1-$2)} END{if(sum<0.5) printf("1"); else printf("0")}' $HSTA_UNIQ_TMP_FILE"_1.txt")
if [ $break_flag -eq 1 ]  
then
    echo "Converged!"
    #break;
fi

#let "itr_cnt=$itr_cnt+1"
#done
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


## ------------------------- Step 5 (trivial?) -----------------------------
## ----------- Running hotspot and get the temperature info ----------------
## we need to decide how often to do this
## Generating the .ptrace for hotspot
# cd $HSTA_TIMING_DIR
# echo "After convergence, report hotspot file generation time..."
# cycle_period_to_involve_temp=10
# if [ $hotspot_cycle_cnt -eq $cycle_period_to_involve_temp ]
# then
#     /usr/bin/time ./hotspot_pp_interface.sh 1
#     echo "Entering $HSTA_THERMAL_DIR..."
#     cd $HSTA_THERMAL_DIR
#     echo "After convergence, report hotspot running time..."
#     /usr/bin/time ./Run_hotspot.sh
#     echo
# else
#     /usr/bin/time ./hotspot_pp_interface.sh 0
# fi
# echo
# let "hotspot_cycle_cnt=$hotspot_cycle_cnt+1"

## Extract the info from the steady file
#awk '/^region/ {print $2}' $HSTA_STEADY_FILE #/^region/ specify nothing before "region"

## ------------------------------- Step 6 ----------------------------------
## -------------------------- Path selection -------------------------------


## ------------------------------- Step 7 ----------------------------------
## --- Gate delay update considering PVT variation and power grid update ---
## -------------- Incremental STA and false path detection -----------------

echo "Entering $HSTA_TIMING_DIR..."
cd $HSTA_TIMING_DIR
## Timing analysis
#if [ "$HSTA_INIT_RUN" == "0" ]
#then
cd $HSTA_TIMING_DIR
echo "Report run_timing.tcl generation time..."
/usr/bin/time ./run_timing_gen.sh > $HSTA_BENCHMARK_DIR"/run_timing_"$set_id"_"$is_pred".tcl"
echo
#exit
#fi
echo "Report timing analysis time..."
#/usr/bin/time ./Timing_analysis.sh pt_scripts.tcl
/usr/bin/time pt_shell -f $HSTA_BENCHMARK_DIR"/run_timing_"$set_id"_"$is_pred".tcl"
if [ $? -ne 0 ]
then
    echo "Timing analysis failed!!!"
    exit
fi
./rpt_parser.sh
echo

echo "Entering Benchmark dir to remove the temp files..."
cd $HSTA_BENCHMARK_DIR
rm `ls *temp*`
#done